package choreganizer;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;



public class SavingProgressGlassPane
extends JComponent 
implements TimerDelegate, MouseListener
{

	private Thread				animation;
	private String 			text;
	private String				textHolder;
	private RenderingHints 	rendHints;
	private int     			alphaLevel;
	private int					ticks = 3;
	private int					currentTick;
	private boolean			fadeIn;
	private boolean			fadeOut;
	private boolean			keepAlive;
	private TextLayout		maxLayout;
	private long 				minimumRunTime;
	
	
	public SavingProgressGlassPane()
	{
		this("");
	}
	
	
	public SavingProgressGlassPane(String text)
	{
		text.trim();
		textHolder = text;	// Put the actual text in a placeholder till we've faded in
		this.text = null;		// Set text to null for now
		rendHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
		rendHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      rendHints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
		
		alphaLevel = 0;
		setOpaque(false);
	}
	
	
	/*
	* This will gracefully insert the glass pane,
	* fading the program out
	*/
	public void start()
	{
		minimumRunTime = System.currentTimeMillis() + 2000;
		alphaLevel = 0;
		currentTick = 0;
		keepAlive = true;
		fadeIn = true;
		addMouseListener(this);
		setVisible(true);
		animation = new Thread(new Animator());
		animation.start();
	}
	
	
	
	/*
	* This will gracefully remove the glass pane, 
	* fading the program back in
	*/
	public void stop()
	{
		if (animation != null) 
		{
			fadeOut = true;
			animation = null;
		}
	}
	
	
	/*
	* This will immediately get rid of the glass pane
	*/
	public void interrupt()
	{
		if (animation != null) 
		{
			animation.interrupt();
			animation = null;
			
			removeMouseListener(this);
			setVisible(false);
			repaint();
		}
	}
	
	
	public void paintComponent(Graphics g)
	{
		int width  = getWidth();
		int height = getHeight();
		
		// Set the rendering hints
		Graphics2D g2 = (Graphics2D)g;
		g2.setRenderingHints(rendHints);
		
		// Set the alpha level
		//g2.setColor(new Color(255, 255, 255, (int) (alphaLevel * shield)));
		g2.setColor(new Color(255, 255, 255, (int) (alphaLevel)));
		g2.fillRect(0, 0, getWidth(), getHeight());
		
		// Draw the text to the screen
		if (text != null)
		{
			Font lFont = new Font( getFont().getName(), Font.BOLD, 30 );
			FontRenderContext context = g2.getFontRenderContext();
			
			// Determine the size along w/ the periods
			if (maxLayout == null)
			{
				StringBuilder sb = new StringBuilder();
				sb.append(text);
				for (int i=0; i<ticks; i++)
					sb.append(".");
				
				maxLayout = new TextLayout(sb.toString(), lFont, context);
			}
			
			String tmpText = text;
			currentTick++;
			if (currentTick > ticks)
				currentTick = 0;
			
			for (int i=0; i < currentTick; i++)
				tmpText += ".";
			
			TextLayout layout = new TextLayout(tmpText, lFont, context);
			Rectangle2D bounds = maxLayout.getBounds();
			g2.setColor(getForeground());
			
			// Center drawn text
			layout.draw(
				g2, 
				(float)(width-bounds.getWidth())/2, 
				(float)(height-bounds.getHeight())/2
			);
		}
	}
	
	
	
	private boolean threadStopCheck()
	{
		if (!keepAlive && System.currentTimeMillis() >= minimumRunTime && !fadeOut && !fadeIn)
			return false;
		else
			return true;
	}
	
	protected class Animator implements Runnable
	{
		public void run()
		{
			// First we'll create a fade-in by increasing the alpha
			// Then we'll continuously loop a small animation
			// When the program wants to stop, we'll be used to fade-out
			while (!Thread.interrupted() && threadStopCheck())
			{
				if (fadeIn)
				{
					if (alphaLevel < 140)
						alphaLevel += 5;
					else
					{
						fadeIn = false;
						text = textHolder;
					}
				}
				
				if (fadeOut && System.currentTimeMillis() >= minimumRunTime)
				{
					if (text != null)
						text = null;
					if (alphaLevel > 0)
						alphaLevel -= 5;
					else
					{
						fadeOut = false;
						keepAlive = false;
					}
				}
				
				// Call repaint to enact any animations
				repaint();
				
				// Control the animation framerate
				try {
					if (fadeIn || (fadeOut && System.currentTimeMillis() >= minimumRunTime))
						Thread.sleep(5);
					else
						Thread.sleep(180);
				} catch (InterruptedException ie) {
					setVisible(false);
					removeMouseListener(SavingProgressGlassPane.this);
					repaint();
					break;
				}
				
				// Check if any other threads need to work
				Thread.yield();
			}
			
			// Thread is stopping, cleanup
			setVisible(false);
			removeMouseListener(SavingProgressGlassPane.this);
			repaint();
		}
		
	}
	
	
	
	/*
	* We implement the mouse listeners simply to intercept
	* events, and to keep them from bubbling down
	*/
	public void mouseClicked(MouseEvent e){}
	public void mousePressed(MouseEvent e){}
	public void mouseReleased(MouseEvent e){}
	public void mouseEntered(MouseEvent e){}
	public void mouseExited(MouseEvent e){}
}
